Improve error message on failed compile
authorYehuda Katz <wycats@gmail.com>
Fri, 18 Jul 2014 11:49:34 +0000 (04:49 -0700)
committerYehuda Katz <wycats@gmail.com>
Mon, 21 Jul 2014 17:38:31 +0000 (10:38 -0700)
src/cargo/lib.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/util/errors.rs
src/cargo/util/mod.rs
tests/support/mod.rs
tests/test_cargo_compile.rs

index 0b612680407487465df2960c6639b8c2473ed6f4..e7b7c491403a46fba526ee39ccd67f58d302d80d 100644 (file)
@@ -209,7 +209,9 @@ pub fn handle_error(err: CliError, shell: &mut MultiShell) {
     }
 
     let _ = shell.verbose(|shell| {
-        let _ = handle_cause(error, shell);
+        error.cause().map(|err| {
+            let _ = handle_cause(err, shell);
+        });
         Ok(())
       });
 
index df41155393369de517e38b42acbb80efa505b60b..16c0976f5f86ed1ff307f26e424e398c931d47cb 100644 (file)
@@ -3,7 +3,7 @@ use std::collections::HashSet;
 
 use core::{Package, PackageId, PackageSet, Target, Resolve};
 use util;
-use util::{CargoResult, ProcessBuilder, CargoError, human};
+use util::{CargoResult, ProcessBuilder, CargoError, ChainError, human, caused_human};
 use util::{Config, Freshness, internal, ChainError};
 
 use self::job::Job;
@@ -187,14 +187,16 @@ fn rustc(package: &Package, target: &Target,
     });
 
     rustcs.move_iter().map(|rustc| {
+        let name = package.get_name().to_string();
+
         Job::new(proc() {
             if primary {
                 log!(5, "executing primary");
-                try!(rustc.exec().map_err(|err| human(err.to_string())))
+                try!(rustc.exec().chain_error(|| human(format!("Could not compile `{}`.", name))))
             } else {
                 log!(5, "executing deps");
                 try!(rustc.exec_with_output().and(Ok(())).map_err(|err| {
-                    human(err.to_string())
+                    caused_human(format!("Could not compile `{}`.\n{}", name, err.output().unwrap()), err)
                 }))
             }
             Ok(Vec::new())
index 902f8cd375fe9ef35f60476a2415bf64706fcf89..51aff2799b574ac1c8e954537622189006219ad0 100644 (file)
@@ -156,24 +156,34 @@ impl Show for ProcessError {
             None => "never executed".to_string()
         };
         try!(write!(f, "{} (status={})", self.msg, exit));
+        self.output().map(|out| { let _ = write!(f, "{}", out); });
+        Ok(())
+    }
+}
+
+impl ProcessError {
+    pub fn output(&self) -> Option<String> {
         match self.output {
             Some(ref out) => {
+                let mut string = String::new();
                 match str::from_utf8(out.output.as_slice()) {
                     Some(s) if s.trim().len() > 0 => {
-                        try!(write!(f, "\n--- stdout\n{}", s));
+                        string.push_str("\n--- stdout\n");
+                        string.push_str(s);
                     }
                     Some(..) | None => {}
                 }
                 match str::from_utf8(out.error.as_slice()) {
                     Some(s) if s.trim().len() > 0 => {
-                        try!(write!(f, "\n--- stderr\n{}", s));
+                        string.push_str("\n--- stderr\n");
+                        string.push_str(s);
                     }
                     Some(..) | None => {}
                 }
-            }
-            None => {}
+                Some(string)
+            },
+            None => None
         }
-        Ok(())
     }
 }
 
@@ -311,3 +321,12 @@ pub fn human<S: Show>(error: S) -> Box<CargoError + Send> {
         is_human: true
     } as Box<CargoError + Send>
 }
+
+pub fn caused_human<S: Show, E: CargoError + Send>(error: S, cause: E) -> Box<CargoError + Send> {
+    box ConcreteCargoError {
+        description: error.to_string(),
+        detail: None,
+        cause: Some(cause.box_error()),
+        is_human: true
+    } as Box<CargoError + Send>
+}
index 71240d00676b6c445c89e8d37445a329c8ce95cf..017b23f2db0a0695fd35f2c005411ca656935633 100644 (file)
@@ -3,7 +3,7 @@ pub use self::process_builder::{process, ProcessBuilder};
 pub use self::result::{Wrap, Require};
 pub use self::errors::{CargoResult, CargoError, BoxError, ChainError, CliResult};
 pub use self::errors::{CliError, FromError, ProcessError};
-pub use self::errors::{process_error, internal_error, internal, human};
+pub use self::errors::{process_error, internal_error, internal, human, caused_human};
 pub use self::paths::realpath;
 pub use self::hex::{to_hex, short_hash};
 pub use self::pool::TaskPool;
index ca94f5088e5e3bdcceb1eeacd9d06d1cc3898ed5..25cf7203e09e7dfd9b5b44753f8386265d0af9f6 100644 (file)
@@ -270,8 +270,8 @@ impl Execs {
                     actual.status.matches_exit_status(code),
                     format!("exited with {}\n--- stdout\n{}\n--- stderr\n{}",
                             actual.status,
-                            str::from_utf8(actual.output.as_slice()),
-                            str::from_utf8(actual.error.as_slice())))
+                            String::from_utf8_lossy(actual.output.as_slice()),
+                            String::from_utf8_lossy(actual.error.as_slice())))
             }
         }
     }
index 39544b3712b67d327b7effff12fea348b0ae0232..5a5529bc3328c0b7ac2d0081d4dc2553d032691e 100644 (file)
@@ -83,8 +83,6 @@ test!(cargo_compile_with_invalid_code {
         .file("Cargo.toml", basic_bin_manifest("foo").as_slice())
         .file("src/foo.rs", "invalid rust code!");
 
-    let target = realpath(&p.root().join("target")).assert();
-
     assert_that(p.cargo_process("cargo-build"),
         execs()
         .with_status(101)
@@ -92,11 +90,9 @@ test!(cargo_compile_with_invalid_code {
 {filename}:1:1: 1:8 error: expected item but found `invalid`
 {filename}:1 invalid rust code!
              ^~~~~~~
-Could not execute process \
-`rustc {filename} --crate-name foo --crate-type bin --out-dir {} -L {} -L {}` (status=101)\n",
-            target.display(),
-            target.display(),
-            target.join("deps").display(),
+Could not compile `foo`.
+
+To learn more, run the command again with --verbose.\n",
             filename = format!("src{}foo.rs", path::SEP)).as_slice()));
 })